using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;

namespace Needle.Utils.Collections
{
    public class RichCollection<T> : Collection<T>, IRichList<T>
    {

        IRichList<T> _items;

        public RichCollection()
            : this(new RichList<T>())
        { }

        public RichCollection(IRichList<T> list)
            : base(list)
        {
            _items = (IRichList<T>)this.Items;
        }

        public void AddRange(IEnumerable<T> collection)
        {
            /* Don't use _items, so we direct all Add's through InsertItem(...) */
            foreach (T item in collection)
                Add(item);
        }

        public IRichList<T> AsReadOnly()
        {
            return _items.AsReadOnly();
        }

        public int BinarySearch(T item)
        {
            return _items.BinarySearch(item);
        }

        public int BinarySearch(T item, IComparer<T> comparer)
        {
            return _items.BinarySearch(item, comparer);
        }

        public int BinarySearch(int index, int count, T item, IComparer<T> comparer)
        {
            return _items.BinarySearch(index, count, item, comparer);
        }

        public IRichList<TOutput> ConvertAll<TOutput>(Converter<T, TOutput> converter)
        {
            return _items.ConvertAll(converter);
        }

        public void CopyTo(T[] array)
        {
            _items.CopyTo(array);
        }

        public void CopyTo(int index, T[] array, int arrayIndex, int count)
        {
            _items.CopyTo(index, array, arrayIndex, count);
        }

        public bool Exists(Predicate<T> match)
        {
            return _items.Exists(match);
        }

        public T Find(Predicate<T> match)
        {
            return _items.Find(match);
        }

        public IRichList<T> FindAll(Predicate<T> match)
        {
            return _items.FindAll(match);
        }

        public int FindIndex(Predicate<T> match)
        {
            return _items.FindIndex(match);
        }

        public int FindIndex(int startIndex, Predicate<T> match)
        {
            return _items.FindIndex(startIndex, match);
        }

        public int FindIndex(int startIndex, int count, Predicate<T> match)
        {
            return _items.FindIndex(startIndex, count, match);
        }

        public T FindLast(Predicate<T> match)
        {
            return _items.FindLast(match);
        }

        public int FindLastIndex(Predicate<T> match)
        {
            return _items.FindLastIndex(match);
        }

        public int FindLastIndex(int startIndex, Predicate<T> match)
        {
            return _items.FindLastIndex(startIndex, match);
        }

        public int FindLastIndex(int startIndex, int count, Predicate<T> match)
        {
            return _items.FindLastIndex(startIndex, count, match);
        }

        public void ForEach(Action<T> action)
        {
            _items.ForEach(action);
        }

        public IRichList<T> GetRange(int index, int count)
        {
            return _items.GetRange(index, count);
        }

        public int IndexOf(T item, int index)
        {
            return _items.IndexOf(item, index);
        }

        public int IndexOf(T item, int index, int count)
        {
            return _items.IndexOf(item, index, count);
        }

        public void InsertRange(int index, IEnumerable<T> collection)
        {
            /* Don't use _items, so that all inserts are routed through InsertItem(..) */
            int count = 0;
            foreach (var item in collection)
                Insert(index + count++, item);
        }

        public int LastIndexOf(T item)
        {
            return _items.LastIndexOf(item);
        }

        public int LastIndexOf(T item, int index)
        {
            return _items.LastIndexOf(item, index);
        }

        public int LastIndexOf(T item, int index, int count)
        {
            return _items.LastIndexOf(item, index, count);
        }

        public int RemoveAll(Predicate<T> match)
        {   /* Don't use _items, so that all removes are routed through RemoveItem(..) */
            int removed = 0;
            for (int i = Count - 1; i >= 0; i--)
                if (match(_items[i]))
                {
                    RemoveAt(i);
                    removed++;
                }
            return removed;
        }

        public void RemoveRange(int index, int count)
        {
            /* Don't use _items, so that all removes are routed through RemoveItem(..) */
            for (int i = index + count - 1; i >= index; i--)
                RemoveAt(i);
        }

        public void Reverse()
        {
            _items.Reverse();
        }

        public void Reverse(int index, int count)
        {
            _items.Reverse(index, count);
        }

        public void Sort()
        {
            _items.Sort();
        }

        public void Sort(Comparison<T> comparison)
        {
            _items.Sort(comparison);
        }

        public void Sort(IComparer<T> comparer)
        {
            _items.Sort(comparer);
        }

        public void Sort(int index, int count, IComparer<T> comparer)
        {
            _items.Sort(index, count, comparer);
        }

        public T[] ToArray()
        {
            return _items.ToArray();
        }

        public bool TrueForAll(Predicate<T> match)
        {
            return _items.TrueForAll(match);
        }
        
    }
}
